package com.jtny.nytb.equipment.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jtny.nytb.equipment.dao.equipment.EquipmentSNDAO;
import com.jtny.nytb.equipment.dao.equipment.EquipmentGatewayRelationDAO;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jtny.component.core.util.PageUtils;
import com.jtny.component.core.util.QueryWrapperUtils;
import com.jtny.component.entity.PageData;
import com.jtny.component.entity.PageParam;
import com.jtny.component.enums.GenericStatusEnum;
import com.jtny.component.exception.ServiceException;
import com.jtny.component.util.Assert;
import com.jtny.component.util.BeanUtils;
import com.jtny.nytb.equipment.dao.equipment.EquipmentInfoDAO;
import com.jtny.nytb.equipment.dao.equipment.EquipmentLabelDAO;
import com.jtny.nytb.equipment.dao.equipment.EquipmentParamDAO;
import com.jtny.nytb.equipment.domain.equipment.*;
import com.jtny.nytb.equipment.dto.equipment.EquipmentModelPageQueryParamDTO;
import com.jtny.nytb.equipment.dto.dataparam.LabelTempDTO;
import com.jtny.nytb.equipment.dto.device.*;
import com.jtny.nytb.equipment.dto.model.ExcelModelParamDTO;
import com.jtny.nytb.equipment.enums.CodeRuleTypeEnum;
import com.jtny.nytb.equipment.errorcode.EquipmentInfoErrorCodeEnum;
import com.jtny.nytb.equipment.errorcode.EquipmentModelErrorCodeEnum;
import com.jtny.nytb.equipment.service.EquipmentInfoService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 智慧能源中心 - zx
 * @package com.jtny.energymonitor.equipment.service.impl
 * @fileName EquipmentInfoServiceImpl.java
 * @createTime 2023年09月19日 22:53
 * @Copyright© 2023 jtny
 * 江投能源技术研究院 版权所有
 */
@Service
@AllArgsConstructor
public class EquipmentInfoServiceImpl implements EquipmentInfoService {
    private EquipmentInfoDAO equipmentInfoDAO;
    private EquipmentParamDAO equipmentParamDAO;
    private EquipmentLabelDAO equipmentLabelDAO;
    private EquipmentSNDAO equipmentSNDAO;
    private EquipmentGatewayRelationDAO equipmentGatewayRelationDAO;

    /**
     * 分页查询设备信息
     *
     * @param pageParam
     * @return
     * @throws ServiceException
     */
    @Override
    public PageData<EquipmentInfoDTO> queryPage(EquipmentInfoQueryPageParamDTO pageParam) throws ServiceException {
        Page<EquipmentInfoDO> page = Page.of(pageParam.getPageNo(), pageParam.getPageSize());
        PageData<EquipmentInfoDO> pageDataForDO = PageUtils.getPageData(equipmentInfoDAO.selectPage(page, queryWrapperAll(pageParam)), pageParam);
        return pageDataForDO.transformData(EquipmentInfoDTO.class);
    }

    /**
     * 按参数列出
     *
     * @param queryParam 设备信息查询页面参数 dto
     * @return {@link List}<{@link EquipmentInfoDTO}>
     * @throws ServiceException 服务异常
     */
    @Override
    public List<EquipmentInfoDTO> listByParam(EquipmentInfoQueryPageParamDTO queryParam) throws ServiceException {
        // 封装查询条件QueryWrapper对象
        List<EquipmentInfoDO> equipmentInfoDOS = equipmentInfoDAO.selectList(queryWrapper(queryParam, Boolean.FALSE));
        return BeanUtils.copyToList(equipmentInfoDOS, EquipmentInfoDTO.class);
    }

    private QueryWrapper<EquipmentInfoDO> queryWrapperAll(EquipmentInfoQueryPageParamDTO pageParam) {
        return queryWrapper(pageParam, true);
    }

    private QueryWrapper<EquipmentInfoDO> queryWrapper(EquipmentInfoQueryPageParamDTO pageParam, Boolean isQueryAll) {
        QueryWrapper<EquipmentInfoDO> queryWrapper = QueryWrapperUtils.getQueryWrapper(pageParam);
        queryWrapper.orderByDesc("id");
        if (isQueryAll && pageParam.getStatus() == null) {
            queryWrapper.ne("status", GenericStatusEnum.DELETED.getValue());
        } else if (pageParam.getStatus() == null) {
            queryWrapper.eq("status", GenericStatusEnum.NORMAL.getValue());
        }
        return queryWrapper;
    }


    /**
     * 修改设备信息
     *
     * @param equipmentInfoDTO
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoDTO update(EquipmentInfoDTO equipmentInfoDTO) throws ServiceException {
        Assert.notNull(equipmentInfoDTO.getId(), EquipmentInfoErrorCodeEnum.PARAM_DEVICE_ID_IS_NULL);
        // 将DTO对象的属性复制给DO对象
        EquipmentInfoDO equipmentInfoDO = BeanUtils.copyToObject(equipmentInfoDTO, EquipmentInfoDO.class);
        Long id = equipmentInfoDO.getId();

        equipmentGatewayRelationDAO.delete(Wrappers.<EquipmentGatewayRelationDO>lambdaQuery()
                .eq(EquipmentGatewayRelationDO::getMcbId, equipmentInfoDO.getDockIdentifier()));
        if (GenericStatusEnum.DELETED.getValue().equals(equipmentInfoDO.getStatus())) {
            // 当使用删除时 delete
            equipmentLabelDAO.delete(Wrappers.<EquipmentLabelDO>lambdaQuery()
                    .eq(EquipmentLabelDO::getEquipmentId, id));
            equipmentParamDAO.delete(Wrappers.<EquipmentParamDO>lambdaQuery()
                    .eq(EquipmentParamDO::getEquipmentId, id));
        } else {
            Assert.isTrue(checkName(equipmentInfoDTO.getName(), equipmentInfoDTO.getId()), EquipmentInfoErrorCodeEnum.PARAM_OBJECT_NAME_REPEATED);
            Assert.isTrue(checkDockIdentifier(equipmentInfoDTO.getDockIdentifier(), equipmentInfoDTO.getId()), EquipmentInfoErrorCodeEnum.PARAM_OBJECT_DOCK_REPEATED);
            EquipmentGatewayRelationDO equipmentGatewayRelationDO = new EquipmentGatewayRelationDO();
            equipmentGatewayRelationDO.setMcbId(equipmentInfoDO.getDockIdentifier());
            equipmentGatewayRelationDO.setGwId(equipmentInfoDTO.getGatewayIdentifier());
            equipmentGatewayRelationDO.setModel(equipmentInfoDTO.getGatewayName());
            equipmentGatewayRelationDAO.insert(equipmentGatewayRelationDO);
        }
        equipmentInfoDAO.updateById(equipmentInfoDO);
        return equipmentInfoDTO;
    }

    /**
     * 通过设备id查询单个设备信息
     *
     * @param id 设备id
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoDTO getById(Long id) throws ServiceException {
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectById(id);
        Assert.notNull(equipmentInfoDO, EquipmentModelErrorCodeEnum.OBJECT_NOT_FIND);
        EquipmentInfoDTO equipmentInfoDTO = BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
        String dockIdentifier = equipmentInfoDTO.getDockIdentifier();
        if (StringUtils.isNotBlank(dockIdentifier)) {
            EquipmentGatewayRelationDO equipmentGatewayRelationDO = equipmentGatewayRelationDAO.selectOne(Wrappers.<EquipmentGatewayRelationDO>lambdaQuery()
                    .eq(EquipmentGatewayRelationDO::getMcbId, dockIdentifier)
                    .last("limit 1"));
            if (equipmentGatewayRelationDO != null) {
                equipmentInfoDTO.setGatewayIdentifier(equipmentGatewayRelationDO.getGwId());
                equipmentInfoDTO.setGatewayName(equipmentGatewayRelationDO.getModel());
            }
        }
        return equipmentInfoDTO;
    }

    /**
     * 更新设备状态
     *
     * @param id     编号
     * @param status 地位
     * @throws ServiceException 服务异常
     */
    @Override
    public void updateEquipmentStatus(Long id, Integer status) throws ServiceException {
        equipmentInfoDAO.update(null, Wrappers.<EquipmentInfoDO>lambdaUpdate()
                .set(EquipmentInfoDO::getStatus, status)
                .eq(EquipmentInfoDO::getId, id));
    }

    /**
     * 通过名字获取设备
     *
     * @param name 名字
     * @return {@link EquipmentInfoDTO}
     * @throws ServiceException 服务异常
     */
    @Override
    public EquipmentInfoDTO getEquipmentByName(String name) throws ServiceException {
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectOne(Wrappers.<EquipmentInfoDO>lambdaQuery()
                .eq(EquipmentInfoDO::getName, name)
                .ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue())
                .last("limit 1"));
        return BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
    }

    /**
     * 通过设备code查询单个设备信息
     *
     * @param code 设备code
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoDTO getByCode(String code) throws ServiceException {
        LambdaQueryWrapper<EquipmentInfoDO> wrappers = Wrappers.<EquipmentInfoDO>lambdaQuery().eq(EquipmentInfoDO::getCode, code)
                .eq(EquipmentInfoDO::getStatus, GenericStatusEnum.NORMAL.getValue())
                .last("limit 1");
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectOne(wrappers);
        Assert.notNull(equipmentInfoDO, EquipmentModelErrorCodeEnum.OBJECT_NOT_FIND.getErrorMessage());
        return BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
    }

    /**
     * 设备参数分页
     *
     * @param pageParam
     * @return
     * @throws ServiceException
     */
    @Override
    public PageData<EquipmentInfoParamDTO> queryPageParam(EquipmentInfoParamPageQueryDTO pageParam) throws ServiceException {
        // 封装查询条件QueryWrapper对象
        QueryWrapper<EquipmentParamDO> queryWrapper = QueryWrapperUtils.getQueryWrapper(pageParam);
        queryWrapper.orderByDesc("id");
        if (ObjectUtils.isEmpty(pageParam.getStatus())) {
            queryWrapper.ne("status", GenericStatusEnum.DELETED.getValue());
        }
        // 分页查询用户信息
        Page<EquipmentParamDO> page = Page.of(pageParam.getPageNo(), pageParam.getPageSize());
        PageData<EquipmentParamDO> pageDataForDO = PageUtils.getPageData(equipmentParamDAO.selectPage(page, queryWrapper), pageParam);
        return pageDataForDO.transformData(EquipmentInfoParamDTO.class);
    }

    /**
     * 保存设备参数
     *
     * @param equipmentInfoParamDTOTwo
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoParamDTO savaParam(EquipmentInfoParamDTO equipmentInfoParamDTOTwo) throws ServiceException {
        if (equipmentInfoParamDTOTwo == null) {
            throw new ServiceException(EquipmentInfoErrorCodeEnum.PARAM_DEVICE_ID_IS_NULL.getErrorCode(), EquipmentInfoErrorCodeEnum.PARAM_DEVICE_ID_IS_NULL.getErrorMessage());
        }
        // 将DTO对象的属性复制给DO对象
        EquipmentParamDO equipmentParamDO = BeanUtils.copyToObject(equipmentInfoParamDTOTwo, EquipmentParamDO.class);
        // 保存操作
        equipmentParamDAO.insert(equipmentParamDO);
        // 将id设置给DTO对象
        equipmentInfoParamDTOTwo.setId(equipmentParamDO.getId());
        return equipmentInfoParamDTOTwo;
    }

    /**
     * 保存设备参数信息List
     *
     * @param equipmentInfoParamList 设备参数信息List
     * @throws ServiceException 服务异常
     */
    @Override
    public void saveParamList(List<EquipmentInfoParamDTO> equipmentInfoParamList) throws ServiceException {
        List<Long> equipmentIdList = equipmentInfoParamList.stream()
                .map(EquipmentInfoParamDTO::getEquipmentId).distinct()
                .collect(Collectors.toList());
        // 删除设备参数
        equipmentParamDAO.delete(Wrappers.<EquipmentParamDO>lambdaQuery()
                .in(EquipmentParamDO::getEquipmentId, equipmentIdList));
        // 保存设备参数
        equipmentParamDAO.insertBatch(BeanUtils.copyToList(equipmentInfoParamList, EquipmentParamDO.class));
    }

    @Override
    public EquipmentInfoParamDTO getByIdParam(Long id) throws ServiceException {
        QueryWrapper<EquipmentParamDO> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("id", id);
        EquipmentParamDO equipmentParamDO = equipmentParamDAO.selectOne(objectQueryWrapper);
        return BeanUtils.copyToObject(equipmentParamDO, EquipmentInfoParamDTO.class);
    }

    /**
     * 修改设备参数
     *
     * @param equipmentInfoParamDTOTwo
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoParamDTO updateParam(EquipmentInfoParamDTO equipmentInfoParamDTOTwo) throws ServiceException {
        Assert.notNull(equipmentInfoParamDTOTwo, EquipmentInfoErrorCodeEnum.PARAM_OBJECT_PARAM_IS_NULL.getErrorMessage());
        // 将DTO对象的属性复制给DO对象
        EquipmentParamDO equipmentParamDO = BeanUtils.copyToObject(equipmentInfoParamDTOTwo, EquipmentParamDO.class);
        equipmentParamDAO.updateById(equipmentParamDO);
        return equipmentInfoParamDTOTwo;
    }

    /**
     * 通过设备code查询设备信息
     *
     * @param code
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoDTO detailsEquCode(String code) throws ServiceException {
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectOne(Wrappers.<EquipmentInfoDO>lambdaQuery()
                .eq(EquipmentInfoDO::getCode, code)
                .ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue())
                .last("limit 1"));
        return BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
    }

    @Override
    public List<EquipmentInfoDTO> detailsEquCodeList(List<String> codes) throws ServiceException {
        LambdaQueryWrapper<EquipmentInfoDO> equipmentInfoDO = new LambdaQueryWrapper<>();
        equipmentInfoDO.in(CollectionUtil.isNotEmpty(codes),EquipmentInfoDO::getCode, codes);
        equipmentInfoDO.ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue());
        List<EquipmentInfoDO> equipmentInfoDOS = equipmentInfoDAO.selectList(equipmentInfoDO);
        return BeanUtils.copyToList(equipmentInfoDOS, EquipmentInfoDTO.class);
    }

    @Override
    public List<EquipmentInfoDTO> listByQueryParam(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO) throws ServiceException {
        List<EquipmentInfoDO> equipmentInfoList = equipmentInfoDAO.selectList(buildWrapper(equipmentModelPageQueryParamDTO));
        return BeanUtils.copyToList(equipmentInfoList, EquipmentInfoDTO.class);
    }

    /**
     * 通过查询参数列出设备 ID
     *
     * @param equipmentModelPageQueryParamDTO 设备型号页面查询参数 DTO
     * @return {@link List}<{@link Long}>
     * @throws ServiceException 服务异常
     */
    @Override
    public List<Long> listEquipmentIdByQueryParam(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO)
            throws ServiceException {
        List<EquipmentInfoDTO> equipmentInfoList = listByQueryParam(equipmentModelPageQueryParamDTO);
        if (CollUtil.isEmpty(equipmentInfoList)) {
            return CollUtil.newArrayList();
        }
        return equipmentInfoList.stream().map(EquipmentInfoDTO::getId).collect(Collectors.toList());
    }

    /**
     * @param equipmentIdList 设备 ID 列表
     * @return {@link Map}<{@link Long}, {@link EquipmentInfoDTO}> key: 设备 ID value: 设备信息
     */
    @Override
    public Map<Long, EquipmentInfoDTO> mapEquipmentInfoByIds(Collection<Long> equipmentIdList) {
        if (CollUtil.isNotEmpty(equipmentIdList)) {
            List<EquipmentInfoDO> equipmentInfoDOList = equipmentInfoDAO.selectBatchIds(equipmentIdList);
            List<EquipmentInfoDTO> list = BeanUtils.copyToList(equipmentInfoDOList, EquipmentInfoDTO.class);
            Map<Long, EquipmentInfoDTO> collect = list.stream().collect(Collectors.toMap(EquipmentInfoDTO::getId, item -> item));
            return collect;
        }
        return new HashMap<>();
    }

    /**
     * 查出所有的设备信息
     *
     * @return
     * @throws ServiceException
     */
    @Override
    public List<EquipmentInfoDTO> getAllDevice() throws ServiceException {
        QueryWrapper<EquipmentInfoDO> deviceQueryWrapper = new QueryWrapper<>();
        deviceQueryWrapper.eq("status", GenericStatusEnum.NORMAL.getValue());
        List<EquipmentInfoDO> equipmentInfoDOS = equipmentInfoDAO.selectList(deviceQueryWrapper);
        return BeanUtils.copyToList(equipmentInfoDOS, EquipmentInfoDTO.class);
    }

    /**
     * 导入设备
     *
     * @param type          类型
     * @param equipmentList 设备清单
     * @return {@link Map}<{@link Long}, {@link String}> key: equipmentId value: equipmentCode
     */
    @Override
    public Map<Long, String> importEquipment(String type, List<EquipmentExcelDTO> equipmentList) {
        Map<Long, String> result = new HashMap<>();
        List<EquipmentInfoDO> toSaveList = BeanUtils.copyToList(equipmentList, EquipmentInfoDO.class);
        List<EquipmentInfoDO> clean2SaveList = checkListName(toSaveList);
        if (CollUtil.isEmpty(clean2SaveList)) {
            return result;
        }
        clean2SaveList.forEach(item -> {
            item.setIsMeasuringPointDevice(CodeRuleTypeEnum.METER.checkType(type));
            item.setStatus(0);
            equipmentInfoDAO.insert(item);
            result.put(item.getId(), item.getCode());
        });
        return result;
    }

    private List<EquipmentInfoDO> checkListName(List<EquipmentInfoDO> toSaveList) {
        Map<String, EquipmentInfoDO> mapName = toSaveList.stream().collect(Collectors.toMap(EquipmentInfoDO::getName, item -> item));
        // 获取所有的设备模型名称
        Set<String> strings = mapName.keySet();
        List<EquipmentInfoDO> equipmentInfoDOList = equipmentInfoDAO.selectList(Wrappers.<EquipmentInfoDO>lambdaQuery()
                .in(EquipmentInfoDO::getName, strings));
        // 如果数据库中没有重复的，直接返回
        if (CollUtil.isEmpty(equipmentInfoDOList)) {
            return toSaveList;
        }
        // 去除已存在的
        equipmentInfoDOList.stream().map(EquipmentInfoDO::getName).forEach(mapName::remove);
        return new ArrayList<>(mapName.values());
    }

    @Override
    public void importEquipmentModelParam(String type, List<ExcelModelParamDTO> equipmentModelParamDTOList) {
        Map<String, List<ExcelModelParamDTO>> listMap = equipmentModelParamDTOList.stream()
                .collect(Collectors.groupingBy(ExcelModelParamDTO::getModelName));
        Map<String, EquipmentInfoDTO> mapModelNameId = mapEquipmentByNameList(type, listMap.keySet());
        for (String modelName : listMap.keySet()) {
            EquipmentInfoDTO idByModelName = mapModelNameId.getOrDefault(modelName, null);
            if (idByModelName == null) {
                continue;
            }
            List<ExcelModelParamDTO> equipmentModelParamList = listMap.get(modelName);
            List<EquipmentParamDO> toSaveBatch = equipmentModelParamList.stream().map(dto -> {
                EquipmentParamDO modelParamDO = BeanUtils.copyToObject(dto, EquipmentParamDO.class);
                modelParamDO.setEquipmentId(idByModelName.getId());
                modelParamDO.setStatus(GenericStatusEnum.NORMAL.getValue());
                return modelParamDO;
            }).collect(Collectors.toList());
            equipmentParamDAO.insertBatch(toSaveBatch);
        }
    }

    /**
     * 设备标签分页
     *
     * @param equipmentId 设备 ID
     * @param param       参数
     * @return {@link PageData}<{@link LabelTempDTO}>
     */
    @Override
    public PageData<LabelTempDTO> queryPageLabel(Long equipmentId, PageParam param) {
        Page<EquipmentLabelDO> page = Page.of(param.getPageNo(), param.getPageSize());
        QueryWrapper<EquipmentLabelDO> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_id", equipmentId);
        IPage<EquipmentLabelDO> selectPage = equipmentLabelDAO.selectPage(page, wrapper);
        return PageUtils.getPageData(selectPage, param).transformData(LabelTempDTO.class);
    }

    /**
     * 设备标签添加
     *
     * @param equipmentId  设备 ID
     * @param labelTempDTO 标签临时 DTO
     */
    @Override
    public void saveLabel(Long equipmentId, LabelTempDTO labelTempDTO) {
        EquipmentLabelDO equipmentLabelDO = BeanUtils.copyToObject(labelTempDTO, EquipmentLabelDO.class);
        equipmentLabelDO.setEquipmentId(equipmentId);
        equipmentLabelDAO.insert(equipmentLabelDO);
    }

    /**
     * 设备标签添加
     *
     * @param equipmentId      设备 ID
     * @param labelTempDTOList 标签临时 DTO
     */
    @Override
    public void saveEquipmentLabelList(Long equipmentId, List<LabelTempDTO> labelTempDTOList) {
        equipmentLabelDAO.delete(Wrappers.<EquipmentLabelDO>lambdaQuery()
                .eq(EquipmentLabelDO::getEquipmentId, equipmentId));
        List<EquipmentLabelDO> toSaveBatch = BeanUtils.copyToList(labelTempDTOList, EquipmentLabelDO.class);
        toSaveBatch.forEach(item -> {
            item.setEquipmentId(equipmentId);
        });
        equipmentLabelDAO.insertBatch(toSaveBatch);
    }

    /**
     * 设备标签删除
     *
     * @param equipmentId 编号
     * @param labelItemId 标签项 ID
     */
    @Override
    public void deleteLabel(Long equipmentId, Long labelItemId) {
        equipmentLabelDAO.delete(Wrappers.<EquipmentLabelDO>lambdaQuery()
                .eq(EquipmentLabelDO::getEquipmentId, equipmentId)
                .eq(EquipmentLabelDO::getLabelItemId, labelItemId));
    }

    /**
     * 按设备 ID 列出设备标签
     *
     * @param equipmentId 设备 ID
     * @return {@link List}<{@link LabelTempDTO}>
     */
    @Override
    public List<LabelTempDTO> listEquipmentLabelByEquipmentId(Long equipmentId) {
        List<EquipmentLabelDO> equipmentLabelDOList = equipmentLabelDAO.selectList(Wrappers.<EquipmentLabelDO>lambdaQuery()
                .eq(EquipmentLabelDO::getEquipmentId, equipmentId));
        return BeanUtils.copyToList(equipmentLabelDOList, LabelTempDTO.class);
    }

    /**
     * 通过设备模型名称获取设备模型id
     *
     * @param equipmentNameList 设备名称List
     * @return
     */
    @Override
    public Map<String, EquipmentInfoDTO> mapEquipmentByNameList(String type, Set<String> equipmentNameList) {
        Map<String, EquipmentInfoDTO> map = new HashMap<>();
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery()
                .in(EquipmentInfoDO::getName, equipmentNameList);
        wrapper.eq(EquipmentInfoDO::getIsMeasuringPointDevice, CodeRuleTypeEnum.METER.checkType(type));
        wrapper.ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue());
        List<EquipmentInfoDO> equipmentInfoList = equipmentInfoDAO.selectList(wrapper);
        for (EquipmentInfoDO equipmentInfo : equipmentInfoList) {
            map.put(equipmentInfo.getName(), BeanUtils.copyToObject(equipmentInfo, EquipmentInfoDTO.class));
        }
        return map;
    }

    /**
     * 通过设备上报标识List获取设备模型id
     *
     * @param dockIdentifierList 设备上报标识List
     * @return
     */
    @Override
    public Map<String, EquipmentInfoDTO> mapEquipmentByDockIdentifierList(String type, Set<String> dockIdentifierList) {
        Map<String, EquipmentInfoDTO> map = new HashMap<>();
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery()
                .in(EquipmentInfoDO::getDockIdentifier, dockIdentifierList);
        wrapper.eq(EquipmentInfoDO::getIsMeasuringPointDevice, CodeRuleTypeEnum.METER.checkType(type));
        wrapper.ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue());
        List<EquipmentInfoDO> equipmentInfoList = equipmentInfoDAO.selectList(wrapper);
        for (EquipmentInfoDO equipmentInfo : equipmentInfoList) {
            map.put(equipmentInfo.getName(), BeanUtils.copyToObject(equipmentInfo, EquipmentInfoDTO.class));
        }
        return map;
    }

    /**
     * 查询设备参数
     *
     * @param equipmentId
     * @return
     * @throws ServiceException
     */
    @Override
    public Map<String, String> queryParams(Long equipmentId) throws ServiceException {
        // 封装查询条件QueryWrapper对象
        LambdaQueryWrapper<EquipmentParamDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentParamDO::getEquipmentId, equipmentId);
        wrapper.eq(EquipmentParamDO::getStatus, GenericStatusEnum.NORMAL.getValue());
        wrapper.orderByDesc(EquipmentParamDO::getId);
        List<EquipmentParamDO> equipmentParams = equipmentParamDAO.selectList(wrapper);
        Map<String, String> map = equipmentParams.stream().collect(Collectors.toMap(EquipmentParamDO::getCode, EquipmentParamDO::getValue));
        return map;
    }

    @Override
    public EquipmentInfoDTO detailsEquDockIdentifier(String dockIdentifier) throws ServiceException {
        QueryWrapper<EquipmentInfoDO> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("dock_identifier", dockIdentifier);
        objectQueryWrapper.eq("status", GenericStatusEnum.NORMAL.getValue());
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectOne(objectQueryWrapper);
        return BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
    }

    @Override
    public List<EquipmentGatewayRelationDTO> listAllRelation() throws ServiceException {
        List<EquipmentGatewayRelationDO> result = equipmentGatewayRelationDAO.selectList(Wrappers.lambdaQuery(EquipmentGatewayRelationDO.class));
        return BeanUtils.copyToList(result, EquipmentGatewayRelationDTO.class);
    }

    /**
     * 通过参量id列表和设备参数获取设备。
     *
     * @param pageQueryParamDTO
     * @return
     */
    @Override
    public PageData<EquipmentInfoDTO> pageDeviceByParams(EquipmentModelPageQueryParamDTO pageQueryParamDTO) {
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = buildWrapper(pageQueryParamDTO);
        wrapper.eq(EquipmentInfoDO::getStatus, GenericStatusEnum.NORMAL.getValue());
        Page<EquipmentInfoDO> page = Page.of(pageQueryParamDTO.getPageNo(), pageQueryParamDTO.getPageSize());
        PageData<EquipmentInfoDO> pageDataForDO = PageUtils.getPageData(equipmentInfoDAO.selectPage(page, wrapper), pageQueryParamDTO);
        return pageDataForDO.transformData(EquipmentInfoDTO.class);
    }

    private LambdaQueryWrapper<EquipmentInfoDO> buildWrapper(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO) {
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery();
        Optional.ofNullable(equipmentModelPageQueryParamDTO.getStatus())
                .ifPresent(status -> wrapper.eq(EquipmentInfoDO::getStatus, status));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getId())
                .ifPresent(id -> wrapper.eq(EquipmentInfoDO::getId, id));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getModel())
                .ifPresent(model -> wrapper.eq(EquipmentInfoDO::getModel, model));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getType())
                .ifPresent(type -> wrapper.eq(EquipmentInfoDO::getType, type));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getBrand())
                .ifPresent(brand -> wrapper.eq(EquipmentInfoDO::getBrand, brand));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getCode())
                .ifPresent(code -> wrapper.eq(EquipmentInfoDO::getCode, code));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getName())
                .ifPresent(name -> wrapper.like(EquipmentInfoDO::getName, name));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getAreaId())
                .ifPresent(areaId -> wrapper.eq(EquipmentInfoDO::getAreaId, areaId));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getAreaIdList())
                .ifPresent(areaIdList -> wrapper.in(EquipmentInfoDO::getAreaId, areaIdList));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getDockIdentifier())
                .ifPresent(dockIdentifier -> wrapper.eq(EquipmentInfoDO::getDockIdentifier, dockIdentifier));
        if (CollectionUtil.isNotEmpty(equipmentModelPageQueryParamDTO.getEquipmentIdList())) {
            wrapper.in(EquipmentInfoDO::getId, equipmentModelPageQueryParamDTO.getEquipmentIdList());
        }
        return wrapper;
    }

    /**
     * 保存设备信息操作
     *
     * @param equipmentInfoDTO
     * @return
     * @throws ServiceException
     */
    @Override
    public EquipmentInfoDTO save(EquipmentInfoDTO equipmentInfoDTO) throws ServiceException {
        Assert.notNull(equipmentInfoDTO, EquipmentInfoErrorCodeEnum.PARAM_OBJECT_IS_NULL);
        Assert.isTrue(checkName(equipmentInfoDTO.getName(), null), EquipmentInfoErrorCodeEnum.PARAM_OBJECT_NAME_REPEATED);
        Assert.isTrue(checkDockIdentifier(equipmentInfoDTO.getDockIdentifier(), null), EquipmentInfoErrorCodeEnum.PARAM_OBJECT_DOCK_REPEATED);
        equipmentInfoDTO.setId(null);
        // 将DTO对象的属性复制给DO对象
        EquipmentInfoDO equipmentInfoDO = BeanUtils.copyToObject(equipmentInfoDTO, EquipmentInfoDO.class);
        // 名字修改
        setEquipmentName(equipmentInfoDO);
        // 保存操作
        equipmentInfoDAO.insert(equipmentInfoDO);
        // 将id设置给DTO对象
        equipmentInfoDTO.setId(equipmentInfoDO.getId());
        return equipmentInfoDTO;
    }

    private void setEquipmentName(EquipmentInfoDO equipmentInfoDO) {
        Long id = equipmentInfoDO.getId();
        if (ObjectUtils.isNotEmpty(id)) {
            String name = equipmentInfoDO.getName();
            EquipmentSNDO equipmentSNDO = equipmentSNDAO.selectOne(Wrappers.<EquipmentSNDO>lambdaQuery()
                    .eq(EquipmentSNDO::getEquipmentName, name)
                    .last("limit 1"));
            if (ObjectUtils.isEmpty(equipmentSNDO)) {
                equipmentInfoDO.setName(name + "-001");
            } else {
                Integer number = equipmentSNDO.getNumber();
                String equipmentName = equipmentSNDO.getEquipmentName();
                equipmentInfoDO.setName(equipmentName + "-" + String.format("%03d", number + 1));
                equipmentSNDO.setNumber(number + 1);
                equipmentSNDAO.updateById(equipmentSNDO);
            }
        }

    }

    /**
     * 通过设备参数id查询多个设备参数信息
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    @Override
    public List<EquipmentInfoParamDTO> getByIdParams(Long id) throws ServiceException {
        QueryWrapper<EquipmentParamDO> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("equipment_id", id);
        List<EquipmentParamDO> equipmentInfoDOS = equipmentParamDAO.selectList(objectQueryWrapper);
        return BeanUtils.copyToList(equipmentInfoDOS, EquipmentInfoParamDTO.class);
    }


    /**
     * 校验名称是否重复
     *
     * @param name 名称
     * @param id   主键ID
     * @return {@link Boolean}
     */
    private Boolean checkName(String name, Long id) {
        if (StringUtils.isBlank(name)) {
            return Boolean.TRUE;
        }
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery().eq(EquipmentInfoDO::getName, name)
                .ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue());
        Optional.ofNullable(id).ifPresent(item -> wrapper.ne(EquipmentInfoDO::getId, item));
        return !equipmentInfoDAO.exists(wrapper);
    }

    /**
     * 校验名称是否重复
     *
     * @param dockIdentifier 名称
     * @param id             主键ID
     * @return {@link Boolean}
     */
    private Boolean checkDockIdentifier(String dockIdentifier, Long id) {
        if (StringUtils.isBlank(dockIdentifier)) {
            return Boolean.TRUE;
        }
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery().eq(EquipmentInfoDO::getDockIdentifier, dockIdentifier)
                .ne(EquipmentInfoDO::getStatus, GenericStatusEnum.DELETED.getValue());
        Optional.ofNullable(id).ifPresent(item -> wrapper.ne(EquipmentInfoDO::getId, item));
        return !equipmentInfoDAO.exists(wrapper);
    }

}
